home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Help / AEGizmos next >
Encoding:
Text File  |  2000-10-29  |  29.6 KB  |  793 lines

  1.  
  2. AEGizmos Help
  3.  
  4.                                                version: 1.3.3
  5.                                                created: 06/13/94 {02:17:40 pm} 
  6.                                            last update: 08/16/00 {02:43:05 pm} 
  7.  
  8.  
  9. Alpha has very extensive support for scripting and inter-application 
  10. communication. 
  11.  
  12.     1) Alpha is completely scriptable in Tcl, which is far better suited for 
  13.        internal scripting than AppleScript.
  14.        
  15.     2) Alpha accepts the required apple events, plus 'dosc', which is used 
  16.        to tell Alpha to execute a Tcl script.
  17.        
  18.     3) Alpha has a command, AEBuild, which allows arbitrarily complicated 
  19.        apple events to be built and sent. 
  20.        
  21.     4) Queue'd replies of messages sent by AEBuild are AEPrint'd and passed 
  22.        to the tcl proc: handleReply (in "appleEvents.tcl").
  23.        
  24.     5) Alpha has several internal handlers to support interaction with 
  25.        Think, but basically the entire interface is done in Tcl using 
  26.        AEBuild. Compiler errors are parsed and passed to the procedure
  27.        proc: handleThinkReply.
  28.  
  29.  
  30.     ----------------------------------------------------------------------
  31.  
  32.  
  33. The following is a text version of the AEBuild/AEPrint docs.
  34.  
  35.           Apple Events    The Æ Builder/Printer
  36.  
  37. Version 1.3.3
  38.  
  39. Jens Peter Alfke
  40. 11 October 1993
  41. AppleScript Team
  42. © Apple Computer, Inc. 1991–1993
  43.  
  44.           Introduction
  45.  
  46.  
  47. OK, What Is It?
  48.  
  49. Even with the helpful Object Support Library routines that assemble common
  50. Apple event object descriptors, building descriptors and events is still a
  51. pain.  I’ve written a library of two functions that make it quick and easy
  52. to build or display Apple event descriptors and the Apple events
  53. themselves.
  54.  
  55. The AEBuild function takes a format string — a description in a very simple
  56. language of an Apple event descriptor — and generates a real descriptor
  57. (which could be a record or list or event) out of it.  The AEPrint function
  58. does the reverse: given an Apple event descriptor, list or record, it
  59. prettyprints it to a string.  (The resulting string, if sent to AEBuild,
  60. would reproduce the original AEDesc structure.)
  61.  
  62. AEBuild can plug variable parameters into the structures it generates — as
  63. with printf, all you do is put marker characters in the format string and
  64. supply the parameter values as extra function arguments.
  65.  
  66. The benefits of using this library are fourfold:
  67.  
  68. • It’s easier for you to write the code to build Apple event structures. 
  69.   You only have to remember one function call and a few simple syntax rules. 
  70.   Your resulting code is also easier to understand.
  71.  
  72. • As of version 1.2, your code is even faster: AEBuild is three to four
  73.   times as fast as the regular Apple Event Manager routines at constructing
  74.   complex structures.  (Your mileage may vary.)
  75.  
  76. • Your code is smaller: the code for AEBuild and the AEStream library is
  77.   about 6k in size, and the overhead for each call is minimal.  (Most of the
  78.   descriptor string consists of the same four-letter codes you’d be using in
  79.   your program code anyway, and the strings can even be stored in resources
  80.   for more code savings.)
  81.         
  82. • AEPrint helps in debugging programs, by turning mysterious AEDesc
  83.   structures into human-readable text.
  84.  
  85.  
  86.         What’s New?
  87.  
  88.  
  89. In version 1.3:
  90.  
  91. • A new function, AEPrintSize, computes how long the string built by
  92.   AEPrint would be, without actually creating it.  This is useful if you want
  93.   to allocate storage for the string dynamically.
  94.  
  95. • AEPrint no longer truncates hex dumps (of unknown descriptors) after 32
  96.   bytes.
  97.  
  98. And in version 1.3.2:
  99.  
  100. • AEPrint no longer uses the stdio library.  This should help reduce code
  101.   size (and eliminate some problems in code resources) but to do it I had to
  102.   cripple floating-point display.  Floating-point descriptors now print as
  103.   the integer part followed by “.XXXX”.
  104.     
  105. And in version 1.3.3:
  106.  
  107. • After a brilliant suggestion by Rob Dye, AEPrint now uses the built in
  108.   float- to-text coercion to display floating-point descriptors.
  109.  
  110. • Fixed a possible problem with AEBuild input strings containing Return
  111.   characters, in the MPW version of the library.
  112.  
  113.  
  114.           How To Call the Functions
  115.  
  116.  
  117. These are all C functions.  They all take variable numbers of arguments, so
  118. they’d be difficult or impossible to call from Pascal, anyway.  (And
  119. remember, kids: there are no Pascal compilers for the PowerPC chip…)
  120.  
  121.                AEBuild
  122.  
  123.     OSErr
  124.     AEBuild(  AEDesc *desc, const char *descriptorStr, ... ),
  125.     vAEBuild( AEDesc *desc, const char *descriptorStr, void *args );
  126.  
  127. AEBuild reads a null-terminated descriptor string (usually a constant,
  128. although it could come from anywhere), parses it and builds a corresponding
  129. AEDesc structure.  (Don’t worry, I’ll describe the syntax of the descriptor
  130. string in the next section.)  If the descriptor string contains magic
  131. parameter-substitution characters (“@”) then corresponding values of the
  132. correct type must be supplied as function arguments, just as with printf.
  133.  
  134. (vAEBuild is analogous to vprintf: Instead of passing the parameters along
  135. with the function, you supply a va_list, as defined in <stdarg.h>, that
  136. points to the parameter list.  It’s otherwise identical.)
  137.  
  138. AEBuild returns an OSErr.  Any errors returned by Apple Event Manager
  139. routines while building the descriptor will be sent back to you.  The most
  140. likely results are memFullErr and errAECoercionFail.  Also likely is
  141. aeBuildSyntaxErr, resulting from an incorrect descriptor string.  (Make
  142. sure to debug your descriptor strings, perhaps using the demo application,
  143. before you put them in programs!)  The basic version of AEBuild just
  144. reports that a syntax error occurred, without giving any additional
  145. information.  If you want to know more (perhaps the string came from a
  146. user, to whom you’d like to report a helpful error message) you can use the
  147. other version of the library.  This version includes a wee bit of extra
  148. code, and two global variables that will contain useful information after a
  149. syntax error:
  150.  
  151.     extern AEBuild_SyntaxErrType
  152.     AEBuild_ErrCode;
  153.     extern long
  154.  
  155.  
  156.                AEBuild_ErrPos;
  157.  
  158.  
  159. AEBuild_ErrCode is an enumerated value that will contain a specific error
  160. code.  The error codes are defined in AEBuild.h. AEBuild_ErrPos will contain
  161. the index into the descriptor string at which the error occurred: usually one
  162. character past the end of the offending token.  AEBuildParameters
  163.  
  164.                AEBuildParameters
  165.  
  166.     OSErr    AEBuildParameters(  AppleEvent *event, 
  167.                                 const char *descriptorStr, ... );
  168.  
  169. AEBuildParameters adds parameters and/or attributes to an existing Apple
  170. event.  descriptorStr specifies the parameters (required and optional) and
  171. attributes.  Its syntax is described below (see especially the Apple Event
  172. Descriptor Strings subsection); it’s almost the same as the syntax for
  173. AEBuild, with a few additions and modifications.
  174.  
  175. (vAEBuildParameters is analogous to vprintf: Instead of passing the
  176. parameters along with the function, you supply a va_list, as defined in
  177. <stdarg.h>, that points to the parameter list.  It’s otherwise identical.)
  178.  
  179.                AEBuildAppleEvent
  180.  
  181.     AEBuildAppleEvent(  AEEventClass theClass, AEEventID theID,
  182.                         DescType addressType, void *addressData, 
  183.                         long addressLength, short returnID, long transactionID,
  184.                         AppleEvent *event, const char *descriptorStr, ... );
  185.  
  186. AEBuildAppleEvent is like AEBuild but builds an Apple event, including
  187. parameters and attributes.  Or, you could say that it’s like
  188. AEBuildParameters but creates the event from scratch.
  189.  
  190. Most of the parameters are just like the parameters to AECreateAppleEvent,
  191. although you pass the target address data directly, instead of via a
  192. pre-built descriptor.  The resulting Apple event will appear in the event
  193. parameter.  descriptorStr specifies the parameters (required and optional)
  194. and attributes.  The syntax is described below (see especially the Apple
  195. Event Descriptor Strings subsection); it’s almost the same as the syntax for
  196. AEBuild, with a few additions and modifications.
  197.  
  198. (vAEBuildAppleEvent is analogous to vprintf: Instead of passing the
  199. parameters along with the function, you supply a va_list, as defined in
  200. <stdarg.h>, that points to the parameter list.  It’s otherwise identical.)
  201.  
  202.                AEPrint
  203.  
  204.     OSErr AEPrint( AEDesc *desc, char *bufStr, long bufSize );
  205.  
  206. AEPrint reads the Apple event descriptor desc and writes a corresponding
  207. descriptor string into the string pointed to by bufStr.  It will write no
  208. more than bufSize characters, including the trailing null character.  Any
  209. errors returned by Apple Event Manager routines will be returned to the
  210. caller; this isn’t very likely unless the AEDesc structure is somehow
  211. corrupt.
  212.  
  213. The descriptor string produced, if sent to AEBuild, will build a descriptor
  214. identical to the original one.  AEPrint tries to detect AERecords that have
  215. been coerced to other types and print them as coerced records.  Structures of
  216. unknown type that can’t be coerced to AERecords are dumped as hex data.
  217.  
  218. AEPrint can also print complete Apple events as well as regular descriptors. 
  219. The syntax of the resulting string for an event is like that used by
  220. AEBuildParameters and AEBuildAppleEvent, except that:
  221.  
  222. •   The string begins with the event class and ID separated by a backslash.
  223. •   the parameter list is surrounded by curly braces.
  224. •   Attributes are also displayed; they look like parameters but are preceded by 
  225.     “&”s.
  226.  
  227. The builder functions do not accept this event syntax yet.  
  228.  
  229.  
  230.                AEPrintSize
  231.  
  232.     OSErr AEPrintSize( AEDesc *desc, long *bufSizeNeeded );
  233.  
  234. AEPrintSize computes the buffer size that AEPrint would require if given the
  235. same descriptor.  (The size is equal to the string length, plus 1 byte for
  236. the trailing null.)  This is handy for pre-flighting AEPrint, if you want to
  237. allocate the buffer dynamically instead of relying on one of fixed size .
  238.  
  239.  
  240.     ----------------------------------------------------------------------
  241.  
  242.  
  243.           Descriptor-String Syntax
  244.  
  245.  
  246. The real meat of all this, of course, is the syntax of the descriptor
  247. strings.  It’s pretty simple: basic data types like numbers and strings can
  248. be described directly, and then built up into lists and records.  I’ve even
  249. provided a pseudo- BNF grammar (next section) for those of you who actually
  250. enjoy reading those things.
  251.  
  252. Basic Types
  253.  
  254. The fundamental data types are:
  255.  
  256. Type            Examples        Type-code       Description
  257. ----            --------        ---------       -----------
  258. Integer         1234            'long' or       A sequence of decimal digits,
  259.                 -5678           'shor'          optionally preceded by a minus
  260.                                                 sign.
  261.  
  262. Enum/Type       whos            'enum'          A magic four-letter code. Will be
  263. Code            longint         (Use coercion   truncated or padded with spaces
  264.                 'long'          to change to    to exactly four characters. If you
  265.                 <=              'type')         put straight or curly single-
  266.                 '8-)'                           quotes around it, it can contain
  267.                 ‘ZQ 5’                          any characters. If not, it can’t
  268.                 m                               contain any of: @‘'“”:-,([{}])
  269.                                                 and can’t begin with a digit.
  270.  
  271. String      “A String.”         'TEXT'          Any sequence of characters
  272.             “Multiple lines                     within open and close curly
  273.             are okay.”                          quotes. Won’t be null-terminated.
  274.  
  275. Hex Data    «4170706C65»        ??              An even number of hex digits
  276.             «0102 03ff          (Must be        between French quotes (Option-
  277.              e b 6 c»           coerced to      \, Option-Shift-\). Whitespace is
  278.                                 some type)      ignored.
  279.  
  280. Yes, you have to use the actual four-letter codes for enums, type codes,
  281. keywords and object types, instead of the mnemonic constants.  Luckily the
  282. codes are semi-mnemonic anyway.  I did it this way to avoid the massive
  283. overhead, both in code size and execution speed, of a symbol table.  You can
  284. find the definitions of the constants in the text file “AEObjects.p”, which
  285. is part of the Apple Events Object Support Library.  
  286.  
  287.  
  288.           Coercion
  289.  
  290.  
  291. Any basic element (except a hex string) by itself is a descriptor, whose
  292. descriptorType is as given in the table.  You can coerce a basic element to a
  293. different type by putting it in parentheses with a type-code placed before
  294. it.  Here are some examples:
  295.  
  296.     sing(1234)
  297.     type(line)
  298.     long(CODE)
  299.     hexd(“A String”)
  300.     'blob'(«4170706C65»)
  301.  
  302. Coercions of numeric values are effected by calling AECoerceDesc; if the
  303. coercion fails, you’ll get an errAECoercionFail error returned to you. 
  304. Coercions of other types just replace the descriptorType field of the
  305. AEDesc.  
  306.  
  307. Hex strings must be coerced to something, since they have no intrinsic type.  
  308.  
  309. You can also coerce nothing, to get a descriptor with zero-length data:
  310.  
  311.     emty()
  312.  
  313. Even the type can be omitted, leaving just (), in which case the type is 'null'.
  314.  
  315.  
  316.           Lists
  317.  
  318.  
  319. To make an AEDescList, just enclose a comma-separated list of descriptors in
  320. square brackets.  For example:
  321.  
  322.     [123, -456, “et cetera”]
  323.     [sing(1234), long(CODE),
  324.      [“wheels”, “within wheels”]]
  325.     []
  326.  
  327. The elements of a list can be of different types, and a list can contain
  328. other lists or records (see below) as elements.
  329.  
  330. Lists cannot be coerced to other types; the type of a list is always 'list'.
  331.  
  332.  
  333.           Records
  334.  
  335.  
  336. An AERecord is indicated by a comma-separated list of elements enclosed in
  337. curly braces.  Each element of a record consists of a keyword (a type-code,
  338. as described under Basic Types) followed by a “:”, followed by a value, which
  339. can be any descriptor: a basic type, a list or another record.  For example:
  340.  
  341.     {x:100, y:-100}
  342.     {'origin': {x:100, y:-100}, extent: {x:500, y:500},
  343.      cont: [1, 5, 25]}
  344.     {}
  345.  
  346. The default type of a record is 'reco'.  Many of the Apple Events Object
  347. Model structures are AERecords that have been coerced to some other data
  348. type, like 'indx' or 'whos'.  You can coerce a record structure to any type
  349. by preceding it with a type code.  For example:
  350.  
  351.     rang{ star: 5, stop: 6}
  352.  
  353. Warning Coercing to an existing type, such as 'bool' or 'TEXT', is a bad
  354. idea.  Anyone parsing the descriptor (including AEPrint) will recognize the
  355. type and assume that the data has the normal interpretation, which in this
  356. case it wouldn’t.  Bad to awful things would happen.  Don’t do it.
  357.  
  358.  
  359.           Apple Events
  360.  
  361.  
  362. The syntax of the formatting string for an entire Apple event (as passed to
  363. AEBuildAppleEvent) is almost identical to that of a record.  Each keyed
  364. element specified in the string becomes a parameter or attribute of the
  365. event.  The differences are:
  366.  
  367. •   There are no curly-braces at the beginning and end of the string.
  368. •   The character “~” before a parameter keyword makes it optional.
  369.  
  370. Here’s an example of how to construct an Open Selection event for the Finder:
  371.  
  372.     AliasHandle parent, itemToOpen;
  373.     const OSType finderSignature = 'MACS';
  374.     AppleEvent event;
  375.     OSErr err;
  376.     
  377.     // Construct the aliases here (not shown)
  378.     
  379.     err= AEBuildEppleEvent(
  380.             'FNDR', 'SOPE',
  381.             typeApplSignature, @finderSignature, sizeof(finderSignature),
  382.             kAutoGenerateReturnID, kAnyTransactionID,
  383.             &event,                                        // Event to be created
  384.             "----: alis(@@), fsel: [alis(@@)]",            // Format string
  385.                 parent,                                    // param for 1st @@
  386.                 itemToOpen                                // param for 2nd @@
  387.     );
  388.     
  389.  
  390.           Substituting Parameters
  391.  
  392.  
  393. To plug your own values into the midst of a descriptor, use the magic “@”
  394. character.  You can use “@” anywhere you can put a basic element like an
  395. integer.  Each “@” is replaced by a value taken from the parameter list sent
  396. to the AEBuild function.  The type of value created depends on the context in
  397. which the “@” is used: in particular, how it’s coerced.
  398.  
  399. Type Coerced to:    Type of fn parameter read:            Comments:
  400. ----------------    --------------------------            ---------
  401. No coercion            AEDesc*                                A plain “@” will be replaced with a
  402.                                                         descriptor parameter.
  403.                                                         
  404. Numeric             (bool, shor,
  405.                     long, sing, doub, exte)    short, short, long, float,
  406.                     short double, double                Remember that THINK C’s double
  407.                                                         corresponds to type 'exte'!
  408.                                                         
  409. TEXT                char*                                Pointer to a null-terminated C string.
  410.  
  411. Any other type        long followed by void*                Expects a length parameter followed by
  412.                                                         a pointer to the descriptor data.
  413.  
  414. Important: Note particularly: that TEXT parameters must be null-terminated 
  415. strings, although the resulting descriptor data will not be null-
  416. terminated; and that the general case expects two parameters: the 
  417. data’s size and location.
  418.  
  419. In addition, you can substitute data from a handle by using two @ signs.  An
  420. “@@” parameter will read a single handle from the parameter list and use the
  421. data pointed to by that handle as the value of the descriptor.  The “@@” must
  422. be coerced so that AEBuild will know what type to make the descriptor;
  423. however, the type coerced to can be anything (the table above is ignored.)
  424.  
  425. This mechanism is still a bit limited, and may well be improved in the future.
  426.  
  427.  
  428.           Descriptor-String Grammar
  429.  
  430.  
  431. Since no language, however small, can be taken seriously unless it comes
  432. fully equipped with a formidable-looking BNF grammar specification, I here
  433. present one.  No attempt has been made to prevent Messrs.  Backus and/or Naur
  434. from rolling over in their respective graves.
  435.  
  436. Character Classification:
  437.  
  438. whitespace    ‘ ’, ‘\r’, ‘\n’, ‘\t’
  439. digit    0 … 9
  440. paren, bracket,
  441. braces    (, ), [, ], {, }
  442. single-quote    '
  443. double quotes    “, ”
  444. hex quotes    «, »
  445. colon    :
  446. comma    ,
  447. at-sign    @
  448. identchar    any other printable character
  449.  
  450. Tokens:
  451.  
  452. ident ::=    identchar (identchar | digit)*    —Padded/truncated
  453.     ' character* '    to exactly 4 chars
  454. integer ::=    [ - ] digit+    —Just as in C
  455. string ::=    “ (character)* ”
  456. hexstring ::=    « (hexdigit | whitespace)* »    —Even no. of digits, please
  457.  
  458. Grammar Rules for AEBuild:
  459.  
  460. formatstring ::=    obj    —This is the top level of syntax
  461. obj ::=    data    —Single AEDesc; shortcut for (data)
  462.     structure    —Un-coerced structure
  463.     ident structure    —Coerced to some other type
  464. structure ::=    ( data )    —Single AEDesc
  465.     [ objectlist ]    —AEList type
  466.     { keywordlist }    —AERecord type
  467. objectlist ::=    «blank»    —Comma-separated list of things
  468.     obj [ , obj ]*
  469. keywordpair ::=    ident : obj    —Keyword/value pair
  470. keywordlist ::=    «blank»    —List of said pairs
  471.     keywordpair [ , keywordpair ]*
  472. data ::=    @    —Gets appropriate data from fn param
  473.     integer    —'shor' or 'long' unless coerced
  474.     ident    —A 4-char type code ('type') unless coerced
  475.     string    —Unterminated text; 'TEXT' type unless coerced
  476.     hexstring    —Raw hex data; must be coerced to some type!
  477.     
  478. Grammar Rules for AEBuildAppleEvent:
  479.  
  480. eventstring ::=    evtkeywordlist    —Top level syntax for AEBuildAppleEvent
  481. evtkeywordpair ::=    [~] ident : obj    —Keyword/value pair
  482. evtkeywordlist ::=    «blank»    —List of said pairs
  483.     evtkeywordpair [ , evtkeywordpair ]*
  484.     
  485. There. Now it’s all crystal-clear, right?
  486.  
  487.  
  488.           An Example & Timing Comparison
  489.  
  490.  
  491. As an example, I’ll take a C function to generate an object descriptor (taken
  492. from a Pascal example in the Object Model ERS, fleshed out and with gobs of
  493. error checking added) and turn it into a call to AEBuild.  The object
  494. descriptor we want to generate is:
  495.  
  496. First line of document 'Spinnaker' whose first word is 'April' and whose
  497. second word is 'is'
  498.  
  499. Then I’ll execute both functions and compare their execution times.
  500.  
  501. C Code Using Object-Packing Library
  502.  
  503. OSErr
  504. BuildByHand( AEDesc *dDocument, AEDesc *theResultObj )
  505. {
  506.  
  507.     OSErr err;
  508.     AEDesc dObjectExamined, dNum, dWord1, dWord2, dAprilText, dIsText,
  509.            dComparison1, dComparison2, dLogicalTerms, dTheTest, dLineOne, dTestedLines;
  510.     
  511.     dObjectExamined.dataHandle =    /* Zero things to start out with so we can safely */
  512.         dNum.dataHandle =               /* execute our fail code if things don't work out */
  513.         dWord1.dataHandle =
  514.         dWord2.dataHandle =
  515.         dAprilText.dataHandle =
  516.         dIsText.dataHandle =
  517.         dComparison1.dataHandle =
  518.         dComparison2.dataHandle =
  519.         dLogicalTerms.dataHandle =
  520.         dTheTest.dataHandle =
  521.         dLineOne.dataHandle =
  522.         dTestedLines.dataHandle =
  523.             NIL;
  524.     
  525.     if( err= AECreateDesc( 'exmn', NIL, 0, &dObjectExamined ) )
  526.         goto fail;
  527.     
  528.     if( err= MakeIndexDescriptor(1,&dNum) )
  529.         goto fail;
  530.     if( err= MakeObjDescriptor( 'word', &dObjectExamined, formIndex, &dNum,
  531.                     false, &dWord1) )
  532.         goto fail;
  533.     if( err= AECreateDesc( 'TEXT', "April", 5, &dAprilText ) )
  534.         goto fail;
  535.     
  536.     AEDisposeDesc(&dNum);
  537.     if( err= MakeIndexDescriptor(2,&dNum) )
  538.         goto fail;
  539.     if( err= MakeObjDescriptor( 'word', &dObjectExamined, formIndex, &dNum,
  540.                     true, &dWord2) )
  541.         goto fail;
  542.     if( err= AECreateDesc( 'TEXT', "is", 2, &dIsText ) )
  543.         goto fail;
  544.     
  545.     if( err= MakeCompDescriptor( '=   ', &dAprilText, &dWord1, true, &dComparison1 ) )
  546.         goto fail;
  547.     if( err= MakeCompDescriptor( '=   ', &dIsText,    &dWord2, true, &dComparison2 ) )
  548.         goto fail;
  549.     
  550.     if( err= AECreateList( NIL, 0, false, &dLogicalTerms ) )
  551.         goto fail;
  552.     if( err= AEPutDesc( dLogicalTerms, 1, dComparison1 ) )
  553.         goto fail;
  554.     if( err= AEPutDesc( dLogicalTerms, 2, dComparison2 ) )
  555.         goto fail;
  556.     
  557.     AEDisposeDesc(&dComparison1);
  558.     AEDisposeDesc(&dComparison2);
  559.     
  560.     if( err= MakeLogicalDescriptor( &dLogicalTerms, 'AND ', true, &dTheTest) )
  561.         goto fail;
  562.     
  563.     if( err= MakeObjDescriptor(classLine,&dDocument,formTest,&dTheTest,true,
  564.                                     &dTestedLines) )
  565.         goto fail;
  566.     
  567.     if( err= MakeIndexDescriptor(1,&dLineOne) )
  568.         goto fail;
  569.     if( err= MakeObjDescriptor( classLine, &dTestedLines, formIndex, &dLineOne,
  570.             true, theResultObj ) )
  571.         goto fail;
  572.     return noErr;
  573.     
  574.     fail:                           /* Clean up in case we couldn't build it */
  575.     AEDisposeDesc(theResultObj);
  576.     AEDisposeDesc(&dObjectExamined);
  577.     AEDisposeDesc(&dNum);
  578.     AEDisposeDesc(&dWord1);
  579.     AEDisposeDesc(&dWord2);
  580.     AEDisposeDesc(&dAprilText);
  581.     AEDisposeDesc(&dIsText);
  582.     AEDisposeDesc(&dComparison1);
  583.     AEDisposeDesc(&dComparison2);
  584.     AEDisposeDesc(&dLogicalTerms);
  585.     AEDisposeDesc(&dTheTest);
  586.     AEDisposeDesc(&dLineOne);
  587.     AEDisposeDesc(&dTestedLines);
  588.     
  589.     return err;
  590. }
  591.  
  592. MPW 3.2b5 C compiled this into 816 bytes of object code.
  593.  
  594. I found that the average time to execute this function was 0.0188 seconds
  595. (Quadra 700) or 0.0113 seconds (IIfx).† Use this figure for comparison only;
  596. your times may vary.  The timing is especially dependent on the number of
  597. blocks in the heap, since so many block allocations and disposals are
  598. happening.
  599.  
  600.  
  601.           AppleScript
  602.  
  603.  
  604. First line of document 'Spinnaker' whose first word is 'April' and whose
  605. second word is 'is'
  606.  
  607. Descriptor String
  608.  
  609. obj{ want:type('line'),
  610.      from: obj{ want: type('line'), from: @, form: 'test',
  611.                 seld: logi{
  612.                            term: [comp{ relo:=, obj1:“April”,
  613.                                         obj2:obj{ want:type('word'), from:exmn(), 
  614.                                                   form:indx, seld:1 }
  615.                                       },
  616.                                   comp{ relo:=, obj1:“is”,
  617.                                         obj2:obj{ want:type('word'), from:exmn(),
  618.                                                   form:indx, seld:2 }
  619.                                       }
  620.                                  ],
  621.                            logc:AND
  622.                          }
  623.               },
  624.      form: 'indx',
  625.      seld: 1
  626. }
  627.  
  628. AEBuild Call
  629.  
  630. char descriptor[] =                /* Same descriptor string as above. Note clever */
  631. "obj{ want:type('line'),"        /* method used to break string across lines. */
  632.     "from: obj{ want: type('line'), from: @, form: 'test',"        /* Note parameter here */
  633.                "seld: logi{"
  634.                           "term: [comp{ relo:=, obj1:“April”,"
  635.                                        "obj2:"
  636.                              "obj{ want:type('word'), from:exmn(), form:indx, seld:1 }},"
  637.                                  "comp{ relo:=, obj1:“is”,"
  638.                                        "obj2:"
  639.                              "obj{ want:type('word'), from:exmn(), form:indx, seld:2 }}"
  640.                                 "],"
  641.                           "logc:AND"
  642.                         "}"
  643.              "},"
  644.     "form: 'indx',"
  645.     "seld: 1"
  646. "}";
  647.  
  648. void PackWordDesc( AEDesc *dDocumentObject )    /* “Spinnaker” descriptor is a parameter */
  649. {
  650.     err = AEBuild(&theResultObj,
  651.                     descriptorString,
  652.                     dDocumentObject);                    /* AEDesc* parameter for "@" */
  653. }
  654.  
  655. MPW 3.2b5 C compiled this into 42 bytes of object code, plus 310 bytes of data 
  656. storage for the string.
  657.  
  658. I found that the average time to execute this function was 0.0049 seconds 
  659. (Quadra 700) or 0.0070 seconds (IIfx). Use this figure for comparison only; your 
  660. times may vary. The timing is dependent on the number of blocks in the heap, 
  661. since heap blocks are being allocated and resized.
  662.  
  663.  
  664.           Timing Conclusions
  665.  
  666.  
  667. With previous versions of this library, there was a 70% increase in
  668. execution time when using the AEBuild routine.  After delivering the bad
  669. news, I wrote: However, if speed does become an issue, there is always the
  670. option of turbocharging AEBuild by having it directly build descriptors
  671. without going through the Apple Event Manager functions at all.  This would
  672. save an incredible number of Memory Manager calls and probably increase
  673. performance severalfold.  Anyone using AEBuild will get all these
  674. improvements for free.  This is exactly what I did in version 1.1.  In
  675. fact, I wrote a library (AEStream) to do it, so you can do it too.  It’s
  676. easy.
  677.  
  678. AEBuild is now 1.5 to 4 times as fast (depending on CPU) as the using the
  679. Apple Event Manager and/or Object Packing Library routines.  (This means
  680. that AEStream was responsible for a threefold speed-up in AEBuild.  Not
  681. bad, when you take into account other overhead like parsing the format
  682. string!)  Needless to say, if you were already using AEBuild you get this
  683. speed increase absolutely free.  Enjoy!
  684.  
  685.  
  686.           The Demo Program
  687.  
  688.  
  689. I’ve included a demonstration program in the distribution.  This is a
  690. program I used to debug the library.  It reads a line of input, uses
  691. AEBuild to translate it into an AEDesc, uses AEPrint to translate the
  692. AEDesc back into a string, and prints each resulting string.  Error codes
  693. are reported, including syntax-error messages.  The source code is provided
  694. in case you want to see how the functions are called.  s Warning The demo
  695. tool does not handle parameter substitution (the “@” character).  If you
  696. try to substitute parameters, messy and unpleasant things may happen.  Use
  697. some numeric value in place of parameters, and then replace it with “@”s
  698. after you paste the string into your program.
  699.  
  700.  
  701.           The Header Files
  702.  
  703.  
  704. Here for your convenience are printouts of the header files as of 21 July 1992.
  705.  
  706. AEBuild.h
  707.  
  708. #define aeBuild_SyntaxErr    12345            /* Let's get an Official OSErr code someday */
  709.  
  710. typedef enum{                                /* Syntax Error Codes: */
  711.     aeBuildSyntaxNoErr = 0,                        /* (No error) */
  712.     aeBuildSyntaxBadToken,                        /* Illegal character */
  713.     aeBuildSyntaxBadEOF,                            /* Unexpected end of format string */
  714.     aeBuildSyntaxNoEOF,                            /* Unexpected extra stuff past end */
  715.     aeBuildSyntaxBadNegative,                    /* "-" not followed by digits */
  716.     aeBuildSyntaxMissingQuote,                    /* Missing close "'" */
  717.     aeBuildSyntaxBadHex,                            /* Non-digit in hex string */
  718.     aeBuildSyntaxOddHex,                            /* Odd # of hex digits */
  719.     aeBuildSyntaxNoCloseHex,                        /* Missing "»" */
  720.     aeBuildSyntaxUncoercedHex,                    /* Hex string must be coerced to a type */
  721.     aeBuildSyntaxNoCloseString,                    /* Missing "”" */
  722.     aeBuildSyntaxBadDesc,                        /* Illegal descriptor */
  723.     aeBuildSyntaxBadData,                        /* Bad data value inside (…) */
  724.     aeBuildSyntaxNoCloseParen,                    /* Missing ")" after data value */
  725.     aeBuildSyntaxNoCloseBracket,                /* Expected "," or "]" */
  726.     aeBuildSyntaxNoCloseBrace,                    /* Expected "," or "}" */
  727.     aeBuildSyntaxNoKey,                            /* Missing keyword in record */
  728.     aeBuildSyntaxNoColon,                        /* Missing ":" after keyword in record */
  729.     aeBuildSyntaxCoercedList,                    /* Cannot coerce a list */
  730.     aeBuildSyntaxUncoercedDoubleAt                /* "@@" substitution must be coerced */
  731. } AEBuild_SyntaxErrType;
  732.  
  733. // In all the "v..." functions, the "args" parameter is really a va_list.
  734. // It's listed as void* here to avoid having to #include stdarg.h.
  735.  
  736. // Building a descriptor:
  737.  
  738. OSErr
  739.     AEBuild(  AEDesc *dst, const char *src, ... ),
  740.     vAEBuild( AEDesc *dst, const char *src, const void *args );
  741.  
  742. // Adding a parameter to an Apple event:
  743.  
  744. OSErr
  745.     AEBuildParameters( AppleEvent *event, const char *format, ... ),
  746.     vAEBuildParameters( AppleEvent *event, const char *format, const void *args );
  747.  
  748. // Building an entire Apple event:
  749.  
  750. OSErr
  751.     AEBuildAppleEvent( AEEventClass theClass, AEEventID theID,
  752.                         DescType addressType, const void *addressData, long addressLength,
  753.                         short returnID, long transactionID, AppleEvent *result,
  754.                         const char *paramsFmt, ... ),
  755.     vAEBuildAppleEvent( AEEventClass theClass, AEEventID theID,
  756.                         DescType addressType, const void *addressData, long addressLength,
  757.                         short returnID, long transactionID, AppleEvent *resultEvt,
  758.                         const char *paramsFmt, const void *args );
  759. AEBuildGlobals.h
  760. /*
  761.  *    AEBuildGlobals.h                            Copyright ©1991 Apple Computer, Inc.
  762.  */
  763.  
  764.  
  765. extern AEBuild_SyntaxErrType
  766.     AEBuild_ErrCode;                    /* Examine after AEBuild returns a syntax error */
  767. extern long
  768.     AEBuild_ErrPos;                    /* Index of error in format string */
  769. AEPrint.h
  770. /*
  771.  *    AEPrint.h                                        Copyright ©1991 Apple Computer, Inc.
  772.  */
  773.  
  774. OSErr AEPrint( AEDesc *desc, char *bufStr, long bufSize );
  775.  
  776.  
  777. † Yes, it really took half again as long on a Quadra!  I think that cache
  778. flushing during the PACK call is responsible.  (It barely slows down at all
  779. when you disable the caches.)
  780.  
  781.  
  782.     ----------------------------------------------------------------------
  783.  
  784.  
  785. Author: Jens Peter Alfke
  786.  
  787. AEGizmos file updated by Craig Barton Upright
  788.  
  789. E-mail: <cupright@princeton.edu>
  790.   mail: Princeton University,  Department of Sociology
  791.         Princeton, New Jersey  08544
  792.    www: <http://www.princeton.edu/~cupright/>
  793.